Step 1: Data Processing
I approach the question by first, quantify the concept of the “education level”. I collected the education background of each president, and if he had a bachelor degree, he can get 1 point. If he had a master degree, then he can get another 1 point. If his univerisity is one of the League Ivy, then he can add 1 more point. So we can seperate the presidents into 4 education levels with score 0,1,2,3.
New Function: Function Maxent_POS_Tag_Annotator() will do the part-of-speech tagging, a process of marking up a word in a text (corpus) as corresponding to a particular part of speech, based on both its definition and its context.
Function sentTag assigns tense to each sentence in the text based on tense principle.
Notice:Since the final dataframe would take about 90 minutes to get, I wrote them into csv.
packages.used=c("rvest", "tibble", "qdap",
"sentimentr", "gplots", "dplyr",
"tm", "syuzhet", "factoextra",
"beeswarm", "scales", "RColorBrewer",
"RANN", "topicmodels","NLP","openNLP","openNLPmodels.en")
# check packages that need to be installed.
packages.needed=setdiff(packages.used,
intersect(installed.packages()[,1],
packages.used))
# install additional packages
if(length(packages.needed)>0){
install.packages(packages.needed, dependencies = TRUE)
}
# load packages
library("rvest")
library("tibble")
library("qdap")
library("sentimentr")
library("gplots")
library("dplyr")
library("tm")
library("syuzhet")
library("factoextra")
library("beeswarm")
library("scales")
library("RColorBrewer")
library("RANN")
library("topicmodels")
library("NLP")
library("openNLP")
library("openNLPmodels.en")
#Inauguaral speeches: scrap speech URLs from <http://www.presidency.ucsb.edu/>.
#main.page <- read_html(x = "http://www.presidency.ucsb.edu/inaugurals.php") #xml2 package
# Get link URLs
# f.speechlinks is a function for extracting links from the list of speeches.
#inaug=f.speechlinks(main.page) #.GlobalEnv
#inaug$links= as.Date(inaug[,1], format="%B %e, %Y")
#inaug=inaug[-nrow(inaug),] # remove the last line, irrelevant due to error.
#write.csv(inaug,"../data/inaug.csv")
inaug<-read.csv("../data/inaug.csv")
inaug.list<-read.csv("../data/inauglist.csv", stringsAsFactors = FALSE)
edu<-read.csv("../data/education background.csv",header = T)
for(i in 1:nrow(inaug.list)){
inaug.list$edulevel[i]<-edu$highlevel[which(edu$President==inaug.list$X...President[i])]
}
#We assemble all scrapped speeches into one list. Note here that we don't have the fulltext
#speech.list=cbind(inaug.list, inaug)
#We scrap the main text part of the transcript's html page. For simple html pages of this kind, [Selectorgadget](http://selectorgadget.com/) is very convenient for identifying the html node that `rvest` can use to scrap its content.
#speech.list$fulltext=NA
#for(i in seq(nrow(speech.list))) {
# text <- read_html(speech.list$urls[i]) %>% # load the page
# html_nodes (".displaytext") %>% # isloate the text #rvest
# html_text() # get the text
# speech.list$fulltext[i]=text
#}
#write.csv(speech.list,"../data/speech.list.csv")
speech.list<-read.csv("../data/speech.list.csv")
# generate list of sentences
#if("ggplot2" %in% (.packages())){
# detach("package:factoextra", unload=TRUE)
# detach("package:ggplot2", unload=TRUE)
#}
#sentence.list=NULL
#for(i in 1:nrow(speech.list)){
# sentences=sent_detect(speech.list$fulltext[i],
# endmarks = c("?", ".", "!", "|",";")) #qdap
# if(length(sentences)>0){
# emotions=get_nrc_sentiment(sentences) #syuzhet
# word.count=word_count(sentences)
# emotions=diag(1/(word.count+0.01))%*%as.matrix(emotions)
# tense=sentTag(sentences)
# sentence.list=rbind(sentence.list,
# cbind(speech.list[i,-ncol(speech.list)],
# sentences=as.character(sentences),
# word.count,
# tense,
# emotions,
# sent.id=1:length(sentences)
# )
# )
# }
#}
#write.csv(sentence.list,"finaldata.csv")
sentence.list<-read.csv("../data/finaldata.csv")
table(sentence.list$tense)
Future Continuous Future Perfect Past Continuous
3 46 7
Past Perfect Past Perfect Continuous Present Continuous
142 2 104
Present Perfect Present Perfect Continuous Simple Future
1095 5 408
Simple Past Simple Present Undefined
717 2179 953
Step 2: Start to compare among four groups.
1. Compare the number of presidents in each cluster and draw a bar plot.
ggplot(as.data.frame(table(inaug.list$edulevel[inaug.list$Term==1]))) +
aes(x=Var1,y=Freq) +
geom_bar(stat="identity",aes(fill=Var1),alpha=0.8) +
ylim(0,15) +
labs(title="Barplot for education levels",
x="Education level score",y="Number of presidents")

2. Compare sentence length distribution of different speeches grouped by presidents’ education level.
Assumption: Those presidents with higher education level may use more long sentences.
sentence.list<-read.csv("../data/finaldata.csv")
sentence.list.sel= na.omit(sentence.list[sentence.list$Term==1,])
sentence.list.sel$File=factor(sentence.list.sel$File)
sentence.list.sel$FileOrdered=reorder(sentence.list.sel$File,
sentence.list.sel$word.count,
mean,
order=T)
tb1=as.data.frame(levels(sentence.list.sel$FileOrdered))
names(tb1) = "File"
tb2 =unique(sentence.list.sel[,c(3,9)])
for(i in 1:nrow(tb1)){
tb1$edulevel[i]<-tb2$edulevel[which(tb2$File==tb1$File[i])]
}
MyColor<-c("gold","darkorange2","brown1","brown4")
eduColor<-factor(tb1$edulevel ,levels = 0:3 ,labels = MyColor)
par(mar=c(4, 11, 2, 2))
beeswarm(word.count~FileOrdered,
data=sentence.list.sel,
horizontal = TRUE,
pch=16,
col =as.character(eduColor),
cex=0.55, cex.axis=0.8, cex.lab=0.8,
spacing=5/nlevels(sentence.list.sel$FileOrdered),
las=2, ylab="", xlab="Number of words in a sentence.",
main="Inaugural Speeches") #beeswarm
legend("topright",legend=levels(factor(tb1$edulevel)),fill=MyColor,cex=1)

Interesting fact1: We find that the most of those presidents with lowest education level(0) used a lot of longer sentences. However, those presidents who used all short sentences in their inaugural speech belong to the high edcation levels (2 and 3). That’s weird, right? Maybe presidents with higher education level wanted to be more easygoing and got closer to general public, so they just used short sentences to win.
3. Compare tense distribution of different speeches grouped by presidents’ education level.
English has three main tenses: present, past, and future, and each of them has sub-tenses. Here are the twelve English tenses: 
sentence.list$File=factor(sentence.list$File)
sentence.list$FileOrdered2=reorder(paste(sentence.list$File,sentence.list$edulevel),
sentence.list$sent.id,
max,
order=T)
par(mar=c(4, 11, 2, 2))
# Assign color to each tense
Tense<-c("Simple Past", "Past Continuous", "Past Perfect", "Past Perfect Continuous", "Simple Present", "Present Continuous", "Present Perfect", "Present Perfect Continuous", "Simple Future","Future Continuous","Future Perfect","Undefined")
MyColors<-c("gold", "greenyellow","green","cyan4","dodgerblue","brown","hotpink", "purple","yellow","orange","firebrick", "grey")
tenseColor<-factor(sentence.list$tense, levels = Tense, labels = MyColors)
# Beeswarm Plot to show the changes of tense during their inauguration.
#pdf("../output/percentofeachtense.pdf",width=8,height=8)
beeswarm(sent.id~FileOrdered2,
data=sentence.list,
horizontal = TRUE,
pch=16, pwcol=as.character(tenseColor),
cex=1, cex.axis=1, cex.lab=1,
spacing=5/nlevels(sentence.list$FileOrdered),
las=2, ylab="", xlab="Sentence ID",
main="Inaugural Speeches")
legend("bottomright", legend = Tense,
title = "Tense", pch = 16, cex=.8, col = MyColors)

Interesting fact2: We can’t see the differences among 4 groups of presidents clearly from this graph. However, we can see that most of Presidents, no matter how their education backgrounds are, did change their tense very often during the inauguration! We can also find that those presidents who haven’t attended a university also like making long speech.
4. Compare the percent of sentences referred to each tense for group0 nd group3.
list0<-sentence.list[sentence.list$edulevel==0,]
count0<-table(list0$tense,factor(list0$File))
count0<-prop.table(count0,2)
count0<-count0[match(Tense,rownames(count0)),]
list3<-sentence.list[sentence.list$edulevel==3,]
count3<-table(list3$tense,factor(list3$File))
count3<-prop.table(count3,2)
count3<-count3[match(Tense,rownames(count3)),]
(apply(count3,1,mean)-apply(count0,1,mean))*100
Simple Past Past Continuous Past Perfect
-2.4356242040 0.0008813523 -1.4317832931
Past Perfect Continuous Simple Present Present Continuous
0.0000000000 3.0851558878 1.1414051138
Present Perfect Present Perfect Continuous Simple Future
-1.5370284862 0.0526277394 -0.3961255510
Future Continuous Future Perfect Undefined
0.0394321767 -0.3938338154 1.8748930797
par(mfrow=c(1, 2), mar=c(9, 2, 4, 7), oma=c(1,1,1,1))
barplot(count0, main="low education level", ylab="Percentage",
col=MyColors,bty='L',
las=2,cex.axis = 0.8, cex.names=0.8)
barplot(count3, main="high education level", ylab="Percentage",
col=MyColors,bty='L',
las=2,cex.axis = 0.8, cex.names=0.8)
par(xpd=TRUE)
legend(9.6,1,legend = Tense,
title = "Tense", cex=0.6, fill = MyColors)

Interesting Fact 3: Presidents with lower education level included relatiely more simple past tense in their speech while presidents with higher education level included relatively more simple present tense in their speech. Maybe presidents with better education like discussing “now” more than “past”.
5. Compare the wordcloud to show the difference of important words across the clusters.
Using the tools of wordcloud package, we can calculate a comparison wordcloud to show the difference of important words across the clusters. In this notebook, we give three results with maximum words of 200 and 1000 respectively.
packages.used=c("tm", "wordcloud", "RColorBrewer", "reshape", "ggplot2",
"dplyr")
# check packages that need to be installed.
packages.needed=setdiff(packages.used,
intersect(installed.packages()[,1],
packages.used))
# install additional packages
if(length(packages.needed)>0){
install.packages(packages.needed, dependencies = TRUE,
repos='http://cran.us.r-project.org')
}
library(tm)
library(wordcloud)
library(RColorBrewer)
library(dplyr)
library(reshape)
library(ggplot2)
unique_edulevel <- sort(unique(speech.list$edulevel))
dataset_merge <- sapply(unique_edulevel ,function(label) list(speech.list[speech.list$edulevel %in% label,ncol(speech.list)] ) )
ff <- lapply(dataset_merge, function(x) Corpus(VectorSource( toString(x) )))
ff.all <- ff[[1]]
for (i in 2:length(unique_edulevel )) {
ff.all<- c(ff.all,ff[[i]])
}
ff.all<-tm_map(ff.all, stripWhitespace) #remove extra white space
ff.all<-tm_map(ff.all, content_transformer(tolower)) #convert all letters to the lower case
ff.all<-tm_map(ff.all, removeWords, stopwords("english")) # remove [stop words]
ff.all<-tm_map(ff.all, removeWords, character(0)) #removed empty words due to formatting errors
ff.all<- tm_map(ff.all, removePunctuation)#remove punctuation
ff.all<- tm_map(ff.all, removeNumbers)
ff.all<- tm_map(ff.all, function(x) removeWords(x,stopwords("english")))
words_to_remove <- c("said","from","what","told","over","more","other","have","last",
"with","this","that","such","when","been","says","will","also",
"where","why","would","today")
ff.all<- tm_map(ff.all, removeWords, words_to_remove)
dtm.all<-TermDocumentMatrix(ff.all) #compute the [Document-Term Matrix (DTM)]
dtm_mat <- as.matrix(dtm.all)
colnames(dtm_mat) <- unique_edulevel
index <- as.logical(sapply(rownames(dtm_mat), function(x) (nchar(x)>3) ))
dtm_mat_long <- dtm_mat[index,]
#pdf("../out/Comparison_cloud_200_small.pdf",height=8,width=8)
comparison.cloud(dtm_mat_long,
max.words=200,
random.order=FALSE,
c(3,1.5),
title.size=1.4)

#dev.off()
#pdf("../out/Comparison_cloud_200.pdf",height=8,width=8)
comparison.cloud(dtm_mat_long,
max.words=200,
random.order=FALSE,
c(1.5,1),
title.size=1.4)

#dev.off()
#pdf("../out/Comparison_cloud_1000.pdf",height=8,width=8)
comparison.cloud(dtm_mat_long,
max.words=1000,
random.order=FALSE,c(1.7,0.8),
title.size=1.4)

6. Compare the word frequency within each group.
We set four frequency levels for this calculation which are 0.25, 0.5, 0.75 and 1. Since a large amount of words are of frequency between 0 and 0.25, we draw a random samples from this class for plotting the word frequency graph.
dtm_mat_long_norm <- apply(dtm_mat_long,2,function(col) col/max(col) )
word_frequency <- melt(dtm_mat_long_norm)
word_frequency <- cbind(word_frequency,
# add colors depending on the score
category=ifelse(word_frequency$value<=0.25,"0.25",
ifelse(word_frequency$value<=0.5, "0.5",
ifelse(word_frequency$value<=0.75, "0.75",
ifelse(word_frequency$value<=1, "1.0","na"))))
)
index <- !word_frequency$category %in% "0.25"
word_frequency2 <- word_frequency[index,]
index <- sample(rownames(word_frequency[word_frequency$category %in% "0.25",]),
500,replace=FALSE)
word_frequency2 <- rbind(word_frequency2,word_frequency[index,])
#write.csv(word_frequency, file="../out/Word frequency.csv",sep="")
#write.csv(word_frequency, file=paste("../out/Word frequency_simplified.csv",sep=""))
#pdf("../out/Frequency of words.pdf",width=8,height=6)
ggplot(word_frequency2) +
aes(x=Docs,y=value) +
geom_text(aes(label=Terms,size=1,colour=category)) +
labs(title="Frequency of words for each cluster",
x="Cluster",y="Frequency of words") +
theme_minimal() +
theme(legend.position="none")

#dev.off()
Interesting Fact 4: Actually, these 2 kind of plots want to show the same thing – Presidents with lower education level considered more about “government” and “people”. But those presidents with better education background considered more about “world” and “nation” , and they used a lot of “must”.
7. Compare the speech topic among 4 education levels.
pdf("../out/speechtopic.pdf",width=8,height=6)
Error in pdf("../out/speechtopic.pdf", width = 8, height = 6) :
cannot open file '../out/speechtopic.pdf'
Interesting Fact 5: We can see that most of those presidents with similar education level had similar topic in their inauguration.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKKyBQcm9qZWN0IHRpdGxlOiBEb2VzIHByZXNpZGVudHMgd2l0aCBoaWdlciBlZHVjYXRpb24gbGV2ZWwgZGVsaXZlciBtb3JlIGNvbXBsZXggaW5hdWd1cmFsIHNwZWVjaD8KKyBUaGlzIHByb2plY3QgaXMgY29uZHVjdGVkIGJ5ICpYaW4gR2FvLCBDb2x1bWJpYSBVTkk6IHhnMjI0OSoKCgojIFN0ZXAgMTogRGF0YSBQcm9jZXNzaW5nIAoKSSBhcHByb2FjaCB0aGUgcXVlc3Rpb24gYnkgZmlyc3QsIHF1YW50aWZ5IHRoZSBjb25jZXB0IG9mIHRoZSAiZWR1Y2F0aW9uIGxldmVsIi4gSSBjb2xsZWN0ZWQgdGhlIGVkdWNhdGlvbiBiYWNrZ3JvdW5kIG9mIGVhY2ggcHJlc2lkZW50LCBhbmQgaWYgaGUgaGFkIGEgYmFjaGVsb3IgZGVncmVlLCBoZSBjYW4gZ2V0IDEgcG9pbnQuIElmIGhlIGhhZCBhIG1hc3RlciBkZWdyZWUsIHRoZW4gaGUgY2FuIGdldCBhbm90aGVyIDEgcG9pbnQuIElmIGhpcyB1bml2ZXJpc2l0eSBpcyBvbmUgb2YgdGhlIExlYWd1ZSBJdnksIHRoZW4gaGUgY2FuIGFkZCAxIG1vcmUgcG9pbnQuIFNvIHdlIGNhbiBzZXBlcmF0ZSB0aGUgcHJlc2lkZW50cyBpbnRvIDQgZWR1Y2F0aW9uIGxldmVscyB3aXRoIHNjb3JlIDAsMSwyLDMuIAoKKipOZXcgRnVuY3Rpb24qKjoKRnVuY3Rpb24gTWF4ZW50X1BPU19UYWdfQW5ub3RhdG9yKCkgIHdpbGwgZG8gdGhlIHBhcnQtb2Ytc3BlZWNoIHRhZ2dpbmcsIGEgcHJvY2VzcyBvZiBtYXJraW5nIHVwIGEgd29yZCBpbiBhIHRleHQgKGNvcnB1cykgYXMgY29ycmVzcG9uZGluZyB0byBhIHBhcnRpY3VsYXIgcGFydCBvZiBzcGVlY2gsIGJhc2VkIG9uIGJvdGggaXRzIGRlZmluaXRpb24gYW5kIGl0cyBjb250ZXh0LiAgCkZ1bmN0aW9uIHNlbnRUYWcgYXNzaWducyB0ZW5zZSB0byBlYWNoIHNlbnRlbmNlIGluIHRoZSB0ZXh0IGJhc2VkIG9uIHRlbnNlIHByaW5jaXBsZS4KCioqTm90aWNlKio6U2luY2UgdGhlIGZpbmFsIGRhdGFmcmFtZSB3b3VsZCB0YWtlIGFib3V0IDkwIG1pbnV0ZXMgdG8gZ2V0LCBJIHdyb3RlIHRoZW0gaW50byBjc3YuICAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwYWNrYWdlcy51c2VkPWMoInJ2ZXN0IiwgInRpYmJsZSIsICJxZGFwIiwgCiAgICAgICAgICAgICAgICAic2VudGltZW50ciIsICJncGxvdHMiLCAiZHBseXIiLAogICAgICAgICAgICAgICAgInRtIiwgInN5dXpoZXQiLCAiZmFjdG9leHRyYSIsIAogICAgICAgICAgICAgICAgImJlZXN3YXJtIiwgInNjYWxlcyIsICJSQ29sb3JCcmV3ZXIiLAogICAgICAgICAgICAgICAgIlJBTk4iLCAidG9waWNtb2RlbHMiLCJOTFAiLCJvcGVuTkxQIiwib3Blbk5MUG1vZGVscy5lbiIpCgojIGNoZWNrIHBhY2thZ2VzIHRoYXQgbmVlZCB0byBiZSBpbnN0YWxsZWQuCnBhY2thZ2VzLm5lZWRlZD1zZXRkaWZmKHBhY2thZ2VzLnVzZWQsIAogICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnNlY3QoaW5zdGFsbGVkLnBhY2thZ2VzKClbLDFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2thZ2VzLnVzZWQpKQojIGluc3RhbGwgYWRkaXRpb25hbCBwYWNrYWdlcwppZihsZW5ndGgocGFja2FnZXMubmVlZGVkKT4wKXsKICBpbnN0YWxsLnBhY2thZ2VzKHBhY2thZ2VzLm5lZWRlZCwgZGVwZW5kZW5jaWVzID0gVFJVRSkKfQoKIyBsb2FkIHBhY2thZ2VzCmxpYnJhcnkoInJ2ZXN0IikKbGlicmFyeSgidGliYmxlIikKbGlicmFyeSgicWRhcCIpCmxpYnJhcnkoInNlbnRpbWVudHIiKQpsaWJyYXJ5KCJncGxvdHMiKQpsaWJyYXJ5KCJkcGx5ciIpCmxpYnJhcnkoInRtIikKbGlicmFyeSgic3l1emhldCIpCmxpYnJhcnkoImZhY3RvZXh0cmEiKQpsaWJyYXJ5KCJiZWVzd2FybSIpCmxpYnJhcnkoInNjYWxlcyIpCmxpYnJhcnkoIlJDb2xvckJyZXdlciIpCmxpYnJhcnkoIlJBTk4iKQpsaWJyYXJ5KCJ0b3BpY21vZGVscyIpCmxpYnJhcnkoIk5MUCIpCmxpYnJhcnkoIm9wZW5OTFAiKQpsaWJyYXJ5KCJvcGVuTkxQbW9kZWxzLmVuIikKCiNJbmF1Z3VhcmFsIHNwZWVjaGVzOiBzY3JhcCBzcGVlY2ggVVJMcyBmcm9tIDxodHRwOi8vd3d3LnByZXNpZGVuY3kudWNzYi5lZHUvPi4KI21haW4ucGFnZSA8LSByZWFkX2h0bWwoeCA9ICJodHRwOi8vd3d3LnByZXNpZGVuY3kudWNzYi5lZHUvaW5hdWd1cmFscy5waHAiKSAjeG1sMiBwYWNrYWdlCiMgR2V0IGxpbmsgVVJMcwojIGYuc3BlZWNobGlua3MgaXMgYSBmdW5jdGlvbiBmb3IgZXh0cmFjdGluZyBsaW5rcyBmcm9tIHRoZSBsaXN0IG9mIHNwZWVjaGVzLiAKI2luYXVnPWYuc3BlZWNobGlua3MobWFpbi5wYWdlKSAjLkdsb2JhbEVudgojaW5hdWckbGlua3M9IGFzLkRhdGUoaW5hdWdbLDFdLCBmb3JtYXQ9IiVCICVlLCAlWSIpCiNpbmF1Zz1pbmF1Z1stbnJvdyhpbmF1ZyksXSAjIHJlbW92ZSB0aGUgbGFzdCBsaW5lLCBpcnJlbGV2YW50IGR1ZSB0byBlcnJvci4KI3dyaXRlLmNzdihpbmF1ZywiLi4vZGF0YS9pbmF1Zy5jc3YiKQppbmF1ZzwtcmVhZC5jc3YoIi4uL2RhdGEvaW5hdWcuY3N2IikKaW5hdWcubGlzdDwtcmVhZC5jc3YoIi4uL2RhdGEvaW5hdWdsaXN0LmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKZWR1PC1yZWFkLmNzdigiLi4vZGF0YS9lZHVjYXRpb24gYmFja2dyb3VuZC5jc3YiLGhlYWRlciA9IFQpCmZvcihpIGluIDE6bnJvdyhpbmF1Zy5saXN0KSl7CiAgaW5hdWcubGlzdCRlZHVsZXZlbFtpXTwtZWR1JGhpZ2hsZXZlbFt3aGljaChlZHUkUHJlc2lkZW50PT1pbmF1Zy5saXN0JFguLi5QcmVzaWRlbnRbaV0pXQp9CgojV2UgYXNzZW1ibGUgYWxsIHNjcmFwcGVkIHNwZWVjaGVzIGludG8gb25lIGxpc3QuIE5vdGUgaGVyZSB0aGF0IHdlIGRvbid0IGhhdmUgdGhlIGZ1bGx0ZXh0CiNzcGVlY2gubGlzdD1jYmluZChpbmF1Zy5saXN0LCBpbmF1ZykKCiNXZSBzY3JhcCB0aGUgbWFpbiB0ZXh0IHBhcnQgb2YgdGhlIHRyYW5zY3JpcHQncyBodG1sIHBhZ2UuIEZvciBzaW1wbGUgaHRtbCBwYWdlcyBvZiB0aGlzIGtpbmQsICBbU2VsZWN0b3JnYWRnZXRdKGh0dHA6Ly9zZWxlY3RvcmdhZGdldC5jb20vKSBpcyB2ZXJ5IGNvbnZlbmllbnQgZm9yIGlkZW50aWZ5aW5nIHRoZSBodG1sIG5vZGUgdGhhdCBgcnZlc3RgIGNhbiB1c2UgdG8gc2NyYXAgaXRzIGNvbnRlbnQuIAojc3BlZWNoLmxpc3QkZnVsbHRleHQ9TkEKI2ZvcihpIGluIHNlcShucm93KHNwZWVjaC5saXN0KSkpIHsKIyAgICB0ZXh0IDwtIHJlYWRfaHRtbChzcGVlY2gubGlzdCR1cmxzW2ldKSAlPiUgIyBsb2FkIHRoZSBwYWdlCiMgICAgaHRtbF9ub2RlcyAoIi5kaXNwbGF5dGV4dCIpICU+JSAjIGlzbG9hdGUgdGhlIHRleHQgI3J2ZXN0CiMgICAgaHRtbF90ZXh0KCkgIyBnZXQgdGhlIHRleHQKIyAgICBzcGVlY2gubGlzdCRmdWxsdGV4dFtpXT10ZXh0CiN9CiN3cml0ZS5jc3Yoc3BlZWNoLmxpc3QsIi4uL2RhdGEvc3BlZWNoLmxpc3QuY3N2IikKc3BlZWNoLmxpc3Q8LXJlYWQuY3N2KCIuLi9kYXRhL3NwZWVjaC5saXN0LmNzdiIpCiMgZ2VuZXJhdGUgbGlzdCBvZiBzZW50ZW5jZXMKCiNpZigiZ2dwbG90MiIgJWluJSAoLnBhY2thZ2VzKCkpKXsKIyAgZGV0YWNoKCJwYWNrYWdlOmZhY3RvZXh0cmEiLCB1bmxvYWQ9VFJVRSkKIyAgZGV0YWNoKCJwYWNrYWdlOmdncGxvdDIiLCB1bmxvYWQ9VFJVRSkgCiN9CiNzZW50ZW5jZS5saXN0PU5VTEwKI2ZvcihpIGluIDE6bnJvdyhzcGVlY2gubGlzdCkpewojICBzZW50ZW5jZXM9c2VudF9kZXRlY3Qoc3BlZWNoLmxpc3QkZnVsbHRleHRbaV0sCiMgICAgICAgICAgICAgICAgICAgICAgICBlbmRtYXJrcyA9IGMoIj8iLCAiLiIsICIhIiwgInwiLCI7IikpICNxZGFwCiMgIGlmKGxlbmd0aChzZW50ZW5jZXMpPjApewojICAgIGVtb3Rpb25zPWdldF9ucmNfc2VudGltZW50KHNlbnRlbmNlcykgI3N5dXpoZXQKIyAgICB3b3JkLmNvdW50PXdvcmRfY291bnQoc2VudGVuY2VzKQojICAgIGVtb3Rpb25zPWRpYWcoMS8od29yZC5jb3VudCswLjAxKSklKiVhcy5tYXRyaXgoZW1vdGlvbnMpCiMgICAgdGVuc2U9c2VudFRhZyhzZW50ZW5jZXMpCiMgICAgc2VudGVuY2UubGlzdD1yYmluZChzZW50ZW5jZS5saXN0LCAKIyAgICAgICAgICAgICAgICAgICAgICAgIGNiaW5kKHNwZWVjaC5saXN0W2ksLW5jb2woc3BlZWNoLmxpc3QpXSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlcz1hcy5jaGFyYWN0ZXIoc2VudGVuY2VzKSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JkLmNvdW50LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVuc2UsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbW90aW9ucywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnQuaWQ9MTpsZW5ndGgoc2VudGVuY2VzKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICkKIyAgfQojfQojd3JpdGUuY3N2KHNlbnRlbmNlLmxpc3QsImZpbmFsZGF0YS5jc3YiKQoKc2VudGVuY2UubGlzdDwtcmVhZC5jc3YoIi4uL2RhdGEvZmluYWxkYXRhLmNzdiIpCgpgYGAKCiMgU3RlcCAyOiBTdGFydCB0byBjb21wYXJlIGFtb25nIGZvdXIgZ3JvdXBzLgoKIyMxLiBDb21wYXJlIHRoZSBudW1iZXIgb2YgcHJlc2lkZW50cyBpbiBlYWNoIGNsdXN0ZXIgYW5kIGRyYXcgYSBiYXIgcGxvdC4KYGBge3IsZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDZ9CiNwZGYoIi4uL291dHB1dC9udW1iZXIucGRmIix3aWR0aD02LGhlaWdodD02KQpnZ3Bsb3QoYXMuZGF0YS5mcmFtZSh0YWJsZShpbmF1Zy5saXN0JGVkdWxldmVsW2luYXVnLmxpc3QkVGVybT09MV0pKSkgKyAKICBhZXMoeD1WYXIxLHk9RnJlcSkgKyAKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsYWVzKGZpbGw9VmFyMSksYWxwaGE9MC44KSArIAogIHlsaW0oMCwxNSkgKyAgCiAgbGFicyh0aXRsZT0iQmFycGxvdCBmb3IgZWR1Y2F0aW9uIGxldmVscyIsCiAgICAgICB4PSJFZHVjYXRpb24gbGV2ZWwgc2NvcmUiLHk9Ik51bWJlciBvZiBwcmVzaWRlbnRzIikKCmBgYAoKCgojIyAyLiBDb21wYXJlIHNlbnRlbmNlIGxlbmd0aCBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IHNwZWVjaGVzIGdyb3VwZWQgYnkgcHJlc2lkZW50cycgZWR1Y2F0aW9uIGxldmVsLgoKKkFzc3VtcHRpb246IFRob3NlIHByZXNpZGVudHMgd2l0aCBoaWdoZXIgZWR1Y2F0aW9uIGxldmVsIG1heSB1c2UgbW9yZSBsb25nIHNlbnRlbmNlcy4qCgpgYGB7cixmaWcud2lkdGggPSA3LCBmaWcuaGVpZ2h0ID0gN30gIApzZW50ZW5jZS5saXN0PC1yZWFkLmNzdigiLi4vZGF0YS9maW5hbGRhdGEuY3N2IikKc2VudGVuY2UubGlzdC5zZWw9IG5hLm9taXQoc2VudGVuY2UubGlzdFtzZW50ZW5jZS5saXN0JFRlcm09PTEsXSkKc2VudGVuY2UubGlzdC5zZWwkRmlsZT1mYWN0b3Ioc2VudGVuY2UubGlzdC5zZWwkRmlsZSkKc2VudGVuY2UubGlzdC5zZWwkRmlsZU9yZGVyZWQ9cmVvcmRlcihzZW50ZW5jZS5saXN0LnNlbCRGaWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlLmxpc3Quc2VsJHdvcmQuY291bnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcj1UKQoKdGIxPWFzLmRhdGEuZnJhbWUobGV2ZWxzKHNlbnRlbmNlLmxpc3Quc2VsJEZpbGVPcmRlcmVkKSkKbmFtZXModGIxKSA9ICJGaWxlIgp0YjIgPXVuaXF1ZShzZW50ZW5jZS5saXN0LnNlbFssYygzLDkpXSkKZm9yKGkgaW4gMTpucm93KHRiMSkpewogIHRiMSRlZHVsZXZlbFtpXTwtdGIyJGVkdWxldmVsW3doaWNoKHRiMiRGaWxlPT10YjEkRmlsZVtpXSldCn0KCgpNeUNvbG9yPC1jKCJnb2xkIiwiZGFya29yYW5nZTIiLCJicm93bjEiLCJicm93bjQiKQplZHVDb2xvcjwtZmFjdG9yKHRiMSRlZHVsZXZlbCAsbGV2ZWxzID0gMDozICxsYWJlbHMgPSBNeUNvbG9yKQoKI3BkZigiLi4vb3V0cHV0L3NlbnRlbmNlbGVuZ3RoLnBkZiIsd2lkdGg9OCxoZWlnaHQ9OCkKcGFyKG1hcj1jKDQsIDExLCAyLCAyKSkKYmVlc3dhcm0od29yZC5jb3VudH5GaWxlT3JkZXJlZCwgCiAgICAgICAgIGRhdGE9c2VudGVuY2UubGlzdC5zZWwsCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLAogICAgICAgICBwY2g9MTYsIAogICAgICAgICBjb2wgPWFzLmNoYXJhY3RlcihlZHVDb2xvciksCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LAogICAgICAgICBzcGFjaW5nPTUvbmxldmVscyhzZW50ZW5jZS5saXN0LnNlbCRGaWxlT3JkZXJlZCksCiAgICAgICAgIGxhcz0yLCB5bGFiPSIiLCB4bGFiPSJOdW1iZXIgb2Ygd29yZHMgaW4gYSBzZW50ZW5jZS4iLAogICAgICAgICBtYWluPSJJbmF1Z3VyYWwgU3BlZWNoZXMiKSAjYmVlc3dhcm0KbGVnZW5kKCJ0b3ByaWdodCIsbGVnZW5kPWxldmVscyhmYWN0b3IodGIxJGVkdWxldmVsKSksZmlsbD1NeUNvbG9yLGNleD0xKQoKCmBgYAoKIyMjIyBJbnRlcmVzdGluZyBmYWN0MTogV2UgZmluZCB0aGF0IHRoZSBtb3N0IG9mIHRob3NlIHByZXNpZGVudHMgd2l0aCBsb3dlc3QgZWR1Y2F0aW9uIGxldmVsKDApIHVzZWQgYSBsb3Qgb2YgbG9uZ2VyIHNlbnRlbmNlcy4gSG93ZXZlciwgdGhvc2UgcHJlc2lkZW50cyB3aG8gdXNlZCBhbGwgc2hvcnQgc2VudGVuY2VzIGluIHRoZWlyIGluYXVndXJhbCBzcGVlY2ggYmVsb25nIHRvIHRoZSBoaWdoIGVkY2F0aW9uIGxldmVscyAoMiBhbmQgMykuIFRoYXQncyB3ZWlyZCwgcmlnaHQ/IE1heWJlIHByZXNpZGVudHMgd2l0aCBoaWdoZXIgZWR1Y2F0aW9uIGxldmVsIHdhbnRlZCB0byBiZSBtb3JlIGVhc3lnb2luZyBhbmQgZ290IGNsb3NlciB0byBnZW5lcmFsIHB1YmxpYywgc28gdGhleSBqdXN0IHVzZWQgc2hvcnQgc2VudGVuY2VzIHRvIHdpbi4KCgojIyAzLiBDb21wYXJlIHRlbnNlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbnQgc3BlZWNoZXMgZ3JvdXBlZCBieSBwcmVzaWRlbnRzJyBlZHVjYXRpb24gbGV2ZWwuIApFbmdsaXNoIGhhcyB0aHJlZSBtYWluIHRlbnNlczogcHJlc2VudCwgcGFzdCwgYW5kIGZ1dHVyZSwgYW5kIGVhY2ggb2YgdGhlbSBoYXMgc3ViLXRlbnNlcy4gSGVyZSBhcmUgdGhlIHR3ZWx2ZSBFbmdsaXNoIHRlbnNlczoKIVtpbWFnZV0oLi4vZmlncy8xMlRlbnNlcy5wbmcpCmBgYHtyLGZpZy53aWR0aCA9IDcsIGZpZy5oZWlnaHQgPSA3fQpzZW50ZW5jZS5saXN0JEZpbGU9ZmFjdG9yKHNlbnRlbmNlLmxpc3QkRmlsZSkKCnNlbnRlbmNlLmxpc3QkRmlsZU9yZGVyZWQyPXJlb3JkZXIocGFzdGUoc2VudGVuY2UubGlzdCRGaWxlLHNlbnRlbmNlLmxpc3QkZWR1bGV2ZWwpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlLmxpc3Qkc2VudC5pZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXI9VCkKcGFyKG1hcj1jKDQsIDExLCAyLCAyKSkKCiMgQXNzaWduIGNvbG9yIHRvIGVhY2ggdGVuc2UgClRlbnNlPC1jKCJTaW1wbGUgUGFzdCIsICJQYXN0IENvbnRpbnVvdXMiLCAiUGFzdCBQZXJmZWN0IiwgIlBhc3QgUGVyZmVjdCBDb250aW51b3VzIiwgIlNpbXBsZSBQcmVzZW50IiwgIlByZXNlbnQgQ29udGludW91cyIsICJQcmVzZW50IFBlcmZlY3QiLCAiUHJlc2VudCBQZXJmZWN0IENvbnRpbnVvdXMiLCAiU2ltcGxlIEZ1dHVyZSIsIkZ1dHVyZSBDb250aW51b3VzIiwiRnV0dXJlIFBlcmZlY3QiLCJVbmRlZmluZWQiKQpNeUNvbG9yczwtYygiZ29sZCIsICJncmVlbnllbGxvdyIsImdyZWVuIiwiY3lhbjQiLCJkb2RnZXJibHVlIiwiYnJvd24iLCJob3RwaW5rIiwgInB1cnBsZSIsInllbGxvdyIsIm9yYW5nZSIsImZpcmVicmljayIsICJncmV5IikKdGVuc2VDb2xvcjwtZmFjdG9yKHNlbnRlbmNlLmxpc3QkdGVuc2UsIGxldmVscyA9IFRlbnNlLCBsYWJlbHMgPSBNeUNvbG9ycykKIyBCZWVzd2FybSBQbG90IHRvIHNob3cgdGhlIGNoYW5nZXMgb2YgdGVuc2UgZHVyaW5nIHRoZWlyIGluYXVndXJhdGlvbi4KI3BkZigiLi4vb3V0cHV0L3RlbnNlZGlzdHJpYnV0aW9uLnBkZiIsd2lkdGg9OCxoZWlnaHQ9OCkKYmVlc3dhcm0oc2VudC5pZH5GaWxlT3JkZXJlZDIsIAogICAgICAgICBkYXRhPXNlbnRlbmNlLmxpc3QsCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLAogICAgICAgICBwY2g9MTYsIHB3Y29sPWFzLmNoYXJhY3Rlcih0ZW5zZUNvbG9yKSwKICAgICAgICAgY2V4PTEsIGNleC5heGlzPTEsIGNleC5sYWI9MSwKICAgICAgICAgc3BhY2luZz01L25sZXZlbHMoc2VudGVuY2UubGlzdCRGaWxlT3JkZXJlZCksCiAgICAgICAgIGxhcz0yLCB5bGFiPSIiLCB4bGFiPSJTZW50ZW5jZSBJRCIsCiAgICAgICAgIG1haW49IkluYXVndXJhbCBTcGVlY2hlcyIpCmxlZ2VuZCgiYm90dG9tcmlnaHQiLCBsZWdlbmQgPSBUZW5zZSwKICAgICAgICAgdGl0bGUgPSAiVGVuc2UiLCBwY2ggPSAxNiwgY2V4PS44LCBjb2wgPSBNeUNvbG9ycykKCmBgYAoKIyMjIyBJbnRlcmVzdGluZyBmYWN0MjogV2UgY2FuJ3Qgc2VlIHRoZSBkaWZmZXJlbmNlcyBhbW9uZyA0IGdyb3VwcyBvZiBwcmVzaWRlbnRzIGNsZWFybHkgZnJvbSB0aGlzIGdyYXBoLiBIb3dldmVyLCB3ZSBjYW4gc2VlIHRoYXQgbW9zdCBvZiBQcmVzaWRlbnRzLCBubyBtYXR0ZXIgaG93IHRoZWlyIGVkdWNhdGlvbiBiYWNrZ3JvdW5kcyBhcmUsIGRpZCBjaGFuZ2UgdGhlaXIgdGVuc2UgdmVyeSBvZnRlbiBkdXJpbmcgdGhlIGluYXVndXJhdGlvbiEgV2UgY2FuIGFsc28gZmluZCB0aGF0IHRob3NlIHByZXNpZGVudHMgd2hvIGhhdmVuJ3QgYXR0ZW5kZWQgYSB1bml2ZXJzaXR5IGFsc28gbGlrZSBtYWtpbmcgbG9uZyBzcGVlY2guCgoKIyMgNC4gQ29tcGFyZSB0aGUgcGVyY2VudCBvZiBzZW50ZW5jZXMgcmVmZXJyZWQgdG8gZWFjaCB0ZW5zZSBmb3IgZ3JvdXAwIG5kIGdyb3VwMy4KYGBge3IsZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDZ9Cmxpc3QwPC1zZW50ZW5jZS5saXN0W3NlbnRlbmNlLmxpc3QkZWR1bGV2ZWw9PTAsXQpjb3VudDA8LXRhYmxlKGxpc3QwJHRlbnNlLGZhY3RvcihsaXN0MCRGaWxlKSkKY291bnQwPC1wcm9wLnRhYmxlKGNvdW50MCwyKQpjb3VudDA8LWNvdW50MFttYXRjaChUZW5zZSxyb3duYW1lcyhjb3VudDApKSxdCgoKbGlzdDM8LXNlbnRlbmNlLmxpc3Rbc2VudGVuY2UubGlzdCRlZHVsZXZlbD09MyxdCmNvdW50MzwtdGFibGUobGlzdDMkdGVuc2UsZmFjdG9yKGxpc3QzJEZpbGUpKQpjb3VudDM8LXByb3AudGFibGUoY291bnQzLDIpCmNvdW50MzwtY291bnQzW21hdGNoKFRlbnNlLHJvd25hbWVzKGNvdW50MykpLF0KCihhcHBseShjb3VudDMsMSxtZWFuKS1hcHBseShjb3VudDAsMSxtZWFuKSkqMTAwCgoKI3BkZigiLi4vb3V0cHV0L3BlcmNlbnRvZmVhY2h0ZW5zZS5wZGYiLHdpZHRoPTgsaGVpZ2h0PTYpCnBhcihtZnJvdz1jKDEsIDIpLCBtYXI9Yyg5LCAyLCA0LCA3KSwgb21hPWMoMSwxLDEsMSkpCmJhcnBsb3QoY291bnQwLCBtYWluPSJsb3cgZWR1Y2F0aW9uIGxldmVsIiwgeWxhYj0iUGVyY2VudGFnZSIsCiAgICAgICAgY29sPU15Q29sb3JzLGJ0eT0nTCcsCiAgICAgICAgbGFzPTIsY2V4LmF4aXMgPSAwLjgsIGNleC5uYW1lcz0wLjgpCmJhcnBsb3QoY291bnQzLCBtYWluPSJoaWdoIGVkdWNhdGlvbiBsZXZlbCIsIHlsYWI9IlBlcmNlbnRhZ2UiLAogICAgICAgIGNvbD1NeUNvbG9ycyxidHk9J0wnLAogICAgICAgIGxhcz0yLGNleC5heGlzID0gMC44LCBjZXgubmFtZXM9MC44KQpwYXIoeHBkPVRSVUUpCmxlZ2VuZCg5LjYsMSxsZWdlbmQgPSBUZW5zZSwKICAgICAgICAgdGl0bGUgPSAiVGVuc2UiLCBjZXg9MC42LCBmaWxsID0gTXlDb2xvcnMpCmBgYAoKIyMjIyBJbnRlcmVzdGluZyBGYWN0IDM6IFByZXNpZGVudHMgd2l0aCBsb3dlciBlZHVjYXRpb24gbGV2ZWwgaW5jbHVkZWQgcmVsYXRpZWx5IG1vcmUgc2ltcGxlIHBhc3QgdGVuc2UgaW4gdGhlaXIgc3BlZWNoIHdoaWxlIHByZXNpZGVudHMgd2l0aCBoaWdoZXIgZWR1Y2F0aW9uIGxldmVsIGluY2x1ZGVkIHJlbGF0aXZlbHkgbW9yZSBzaW1wbGUgcHJlc2VudCB0ZW5zZSBpbiB0aGVpciBzcGVlY2guIE1heWJlIHByZXNpZGVudHMgd2l0aCBiZXR0ZXIgZWR1Y2F0aW9uIGxpa2UgZGlzY3Vzc2luZyAibm93IiBtb3JlIHRoYW4gInBhc3QiLgoKCiAgCgojIyA1LiBDb21wYXJlIHRoZSB3b3JkY2xvdWQgdG8gc2hvdyB0aGUgZGlmZmVyZW5jZSBvZiBpbXBvcnRhbnQgd29yZHMgYWNyb3NzIHRoZSBjbHVzdGVycy4KClVzaW5nIHRoZSB0b29scyBvZiB3b3JkY2xvdWQgcGFja2FnZSwgd2UgY2FuIGNhbGN1bGF0ZSBhIGNvbXBhcmlzb24gd29yZGNsb3VkIHRvIHNob3cgdGhlIGRpZmZlcmVuY2Ugb2YgaW1wb3J0YW50IHdvcmRzIGFjcm9zcyB0aGUgY2x1c3RlcnMuIEluIHRoaXMgbm90ZWJvb2ssIHdlIGdpdmUgdGhyZWUgcmVzdWx0cyB3aXRoIG1heGltdW0gd29yZHMgb2YgMjAwIGFuZCAxMDAwIHJlc3BlY3RpdmVseS4KYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGFja2FnZXMudXNlZD1jKCJ0bSIsICJ3b3JkY2xvdWQiLCAiUkNvbG9yQnJld2VyIiwgInJlc2hhcGUiLCAiZ2dwbG90MiIsCiAgICAgICAgICAgICAgICAiZHBseXIiKQoKIyBjaGVjayBwYWNrYWdlcyB0aGF0IG5lZWQgdG8gYmUgaW5zdGFsbGVkLgpwYWNrYWdlcy5uZWVkZWQ9c2V0ZGlmZihwYWNrYWdlcy51c2VkLCAKICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJzZWN0KGluc3RhbGxlZC5wYWNrYWdlcygpWywxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrYWdlcy51c2VkKSkKIyBpbnN0YWxsIGFkZGl0aW9uYWwgcGFja2FnZXMKaWYobGVuZ3RoKHBhY2thZ2VzLm5lZWRlZCk+MCl7CiAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlcy5uZWVkZWQsIGRlcGVuZGVuY2llcyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICByZXBvcz0naHR0cDovL2NyYW4udXMuci1wcm9qZWN0Lm9yZycpCn0KCmxpYnJhcnkodG0pCmxpYnJhcnkod29yZGNsb3VkKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShkcGx5cikKbGlicmFyeShyZXNoYXBlKQpsaWJyYXJ5KGdncGxvdDIpCgp1bmlxdWVfZWR1bGV2ZWwgPC0gc29ydCh1bmlxdWUoc3BlZWNoLmxpc3QkZWR1bGV2ZWwpKQpkYXRhc2V0X21lcmdlIDwtIHNhcHBseSh1bmlxdWVfZWR1bGV2ZWwgLGZ1bmN0aW9uKGxhYmVsKSBsaXN0KHNwZWVjaC5saXN0W3NwZWVjaC5saXN0JGVkdWxldmVsICVpbiUgbGFiZWwsbmNvbChzcGVlY2gubGlzdCldICkgKQpmZiA8LSBsYXBwbHkoZGF0YXNldF9tZXJnZSwgZnVuY3Rpb24oeCkgQ29ycHVzKFZlY3RvclNvdXJjZSggdG9TdHJpbmcoeCkgKSkpIApmZi5hbGwgPC0gZmZbWzFdXQpmb3IgKGkgaW4gMjpsZW5ndGgodW5pcXVlX2VkdWxldmVsICkpIHsKICBmZi5hbGw8LSBjKGZmLmFsbCxmZltbaV1dKQp9CgpmZi5hbGw8LXRtX21hcChmZi5hbGwsIHN0cmlwV2hpdGVzcGFjZSkgI3JlbW92ZSBleHRyYSB3aGl0ZSBzcGFjZQpmZi5hbGw8LXRtX21hcChmZi5hbGwsIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpICNjb252ZXJ0IGFsbCBsZXR0ZXJzIHRvIHRoZSBsb3dlciBjYXNlCmZmLmFsbDwtdG1fbWFwKGZmLmFsbCwgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKSAjIHJlbW92ZSBbc3RvcCB3b3Jkc10KZmYuYWxsPC10bV9tYXAoZmYuYWxsLCByZW1vdmVXb3JkcywgY2hhcmFjdGVyKDApKSAjcmVtb3ZlZCBlbXB0eSB3b3JkcyBkdWUgdG8gZm9ybWF0dGluZyBlcnJvcnMKZmYuYWxsPC0gdG1fbWFwKGZmLmFsbCwgcmVtb3ZlUHVuY3R1YXRpb24pI3JlbW92ZSBwdW5jdHVhdGlvbgpmZi5hbGw8LSB0bV9tYXAoZmYuYWxsLCByZW1vdmVOdW1iZXJzKQpmZi5hbGw8LSB0bV9tYXAoZmYuYWxsLCBmdW5jdGlvbih4KSByZW1vdmVXb3Jkcyh4LHN0b3B3b3JkcygiZW5nbGlzaCIpKSkKd29yZHNfdG9fcmVtb3ZlIDwtIGMoInNhaWQiLCJmcm9tIiwid2hhdCIsInRvbGQiLCJvdmVyIiwibW9yZSIsIm90aGVyIiwiaGF2ZSIsImxhc3QiLAogICAgICAgICAgICAgICAgICAgICAid2l0aCIsInRoaXMiLCJ0aGF0Iiwic3VjaCIsIndoZW4iLCJiZWVuIiwic2F5cyIsIndpbGwiLCJhbHNvIiwKICAgICAgICAgICAgICAgICAgICAgIndoZXJlIiwid2h5Iiwid291bGQiLCJ0b2RheSIpCmZmLmFsbDwtIHRtX21hcChmZi5hbGwsIHJlbW92ZVdvcmRzLCB3b3Jkc190b19yZW1vdmUpCgpkdG0uYWxsPC1UZXJtRG9jdW1lbnRNYXRyaXgoZmYuYWxsKSAjY29tcHV0ZSB0aGUgW0RvY3VtZW50LVRlcm0gTWF0cml4IChEVE0pXQpkdG1fbWF0IDwtIGFzLm1hdHJpeChkdG0uYWxsKQpjb2xuYW1lcyhkdG1fbWF0KSA8LSB1bmlxdWVfZWR1bGV2ZWwgCmluZGV4IDwtIGFzLmxvZ2ljYWwoc2FwcGx5KHJvd25hbWVzKGR0bV9tYXQpLCBmdW5jdGlvbih4KSAobmNoYXIoeCk+MykgKSkKZHRtX21hdF9sb25nIDwtIGR0bV9tYXRbaW5kZXgsXQoKI3BkZigiLi4vb3V0cHV0L0NvbXBhcmlzb25fY2xvdWRfMjAwX3NtYWxsLnBkZiIsaGVpZ2h0PTgsd2lkdGg9OCkKY29tcGFyaXNvbi5jbG91ZChkdG1fbWF0X2xvbmcsCiAgICAgICAgICAgICAgICAgbWF4LndvcmRzPTIwMCwKICAgICAgICAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICAgICAgICAgYygzLDEuNSksCiAgICAgICAgICAgICAgICAgdGl0bGUuc2l6ZT0xLjQpCiNkZXYub2ZmKCkKCiNwZGYoIi4uL291dHB1dC9Db21wYXJpc29uX2Nsb3VkXzIwMC5wZGYiLGhlaWdodD04LHdpZHRoPTgpCmNvbXBhcmlzb24uY2xvdWQoZHRtX21hdF9sb25nLAogICAgICAgICAgICAgICAgIG1heC53b3Jkcz0yMDAsCiAgICAgICAgICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgICAgICAgIGMoMS41LDEpLAogICAgICAgICAgICAgICAgIHRpdGxlLnNpemU9MS40KQojZGV2Lm9mZigpCgojcGRmKCIuLi9vdXRwdXQvQ29tcGFyaXNvbl9jbG91ZF8xMDAwLnBkZiIsaGVpZ2h0PTgsd2lkdGg9OCkKY29tcGFyaXNvbi5jbG91ZChkdG1fbWF0X2xvbmcsCiAgICAgICAgICAgICAgICAgbWF4LndvcmRzPTEwMDAsCiAgICAgICAgICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLGMoMS43LDAuOCksCiAgICAgICAgICAgICAgICAgdGl0bGUuc2l6ZT0xLjQpCiNkZXYub2ZmKCkKYGBgICAKCgojIyA2LiBDb21wYXJlIHRoZSB3b3JkIGZyZXF1ZW5jeSB3aXRoaW4gZWFjaCBncm91cC4KCldlIHNldCBmb3VyIGZyZXF1ZW5jeSBsZXZlbHMgZm9yIHRoaXMgY2FsY3VsYXRpb24gd2hpY2ggYXJlIDAuMjUsIDAuNSwgMC43NSBhbmQgMS4gU2luY2UgYSBsYXJnZSBhbW91bnQgb2Ygd29yZHMgYXJlIG9mIGZyZXF1ZW5jeSBiZXR3ZWVuIDAgYW5kIDAuMjUsIHdlIGRyYXcgYSByYW5kb20gc2FtcGxlcyBmcm9tIHRoaXMgY2xhc3MgZm9yIHBsb3R0aW5nIHRoZSB3b3JkIGZyZXF1ZW5jeSBncmFwaC4KCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9CmR0bV9tYXRfbG9uZ19ub3JtIDwtIGFwcGx5KGR0bV9tYXRfbG9uZywyLGZ1bmN0aW9uKGNvbCkgY29sL21heChjb2wpICkKCndvcmRfZnJlcXVlbmN5IDwtIG1lbHQoZHRtX21hdF9sb25nX25vcm0pCndvcmRfZnJlcXVlbmN5IDwtIGNiaW5kKHdvcmRfZnJlcXVlbmN5LAogICAgICAgICAgICAgICAgICAgICMgYWRkIGNvbG9ycyBkZXBlbmRpbmcgb24gdGhlIHNjb3JlICAgICAgCiAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnk9aWZlbHNlKHdvcmRfZnJlcXVlbmN5JHZhbHVlPD0wLjI1LCIwLjI1IiwgCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHdvcmRfZnJlcXVlbmN5JHZhbHVlPD0wLjUsICIwLjUiLCAKICAgICAgICAgICAgICAgICAgICBpZmVsc2Uod29yZF9mcmVxdWVuY3kkdmFsdWU8PTAuNzUsICIwLjc1IiwgCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHdvcmRfZnJlcXVlbmN5JHZhbHVlPD0xLCAiMS4wIiwibmEiKSkpKQopCgppbmRleCA8LSAhd29yZF9mcmVxdWVuY3kkY2F0ZWdvcnkgJWluJSAiMC4yNSIKd29yZF9mcmVxdWVuY3kyIDwtIHdvcmRfZnJlcXVlbmN5W2luZGV4LF0KaW5kZXggPC0gc2FtcGxlKHJvd25hbWVzKHdvcmRfZnJlcXVlbmN5W3dvcmRfZnJlcXVlbmN5JGNhdGVnb3J5ICVpbiUgIjAuMjUiLF0pLAogICAgICAgICAgICAgICAgNTAwLHJlcGxhY2U9RkFMU0UpCndvcmRfZnJlcXVlbmN5MiA8LSByYmluZCh3b3JkX2ZyZXF1ZW5jeTIsd29yZF9mcmVxdWVuY3lbaW5kZXgsXSkKI3dyaXRlLmNzdih3b3JkX2ZyZXF1ZW5jeSwgZmlsZT0iLi4vb3V0L1dvcmQgZnJlcXVlbmN5LmNzdiIsc2VwPSIiKQojd3JpdGUuY3N2KHdvcmRfZnJlcXVlbmN5LCBmaWxlPXBhc3RlKCIuLi9vdXQvV29yZCBmcmVxdWVuY3lfc2ltcGxpZmllZC5jc3YiLHNlcD0iIikpCgojcGRmKCIuLi9vdXRwdXQvRnJlcXVlbmN5IG9mIHdvcmRzLnBkZiIsd2lkdGg9OCxoZWlnaHQ9NikKZ2dwbG90KHdvcmRfZnJlcXVlbmN5MikgKwogIGFlcyh4PURvY3MseT12YWx1ZSkgKwogIGdlb21fdGV4dChhZXMobGFiZWw9VGVybXMsc2l6ZT0xLGNvbG91cj1jYXRlZ29yeSkpICsgCiAgbGFicyh0aXRsZT0iRnJlcXVlbmN5IG9mIHdvcmRzIGZvciBlYWNoIGNsdXN0ZXIiLAogICAgICAgeD0iQ2x1c3RlciIseT0iRnJlcXVlbmN5IG9mIHdvcmRzIikgKyAKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpIAojZGV2Lm9mZigpCmBgYAoKIyMjIyBJbnRlcmVzdGluZyBGYWN0IDQ6IEFjdHVhbGx5LCB0aGVzZSAyIGtpbmQgb2YgcGxvdHMgd2FudCB0byBzaG93IHRoZSBzYW1lIHRoaW5nIC0tIFByZXNpZGVudHMgd2l0aCBsb3dlciBlZHVjYXRpb24gbGV2ZWwgY29uc2lkZXJlZCBtb3JlIGFib3V0ICJnb3Zlcm5tZW50IiBhbmQgInBlb3BsZSIuIEJ1dCB0aG9zZSBwcmVzaWRlbnRzIHdpdGggYmV0dGVyIGVkdWNhdGlvbiBiYWNrZ3JvdW5kIGNvbnNpZGVyZWQgbW9yZSBhYm91dCAid29ybGQiIGFuZCAibmF0aW9uIiAsIGFuZCB0aGV5IHVzZWQgYSBsb3Qgb2YgIm11c3QiLgoKCiMjIDcuIENvbXBhcmUgdGhlIHNwZWVjaCB0b3BpYyBhbW9uZyA0IGVkdWNhdGlvbiBsZXZlbHMuCgpgYGB7cn0KcHJlc2lkLnN1bW1hcnk9dGJsX2RmKHNlbnRlbmNlLmxpc3Quc2VsKSU+JSAgI2RwbHlyCiAgICBncm91cF9ieShGaWxlKSU+JQogICAgc3VtbWFyaXNlKAogICAgYW5nZXI9bWVhbihhbmdlciksCiAgICBhbnRpY2lwYXRpb249bWVhbihhbnRpY2lwYXRpb24pLAogICAgZGlzZ3VzdD1tZWFuKGRpc2d1c3QpLAogICAgZmVhcj1tZWFuKGZlYXIpLAogICAgam95PW1lYW4oam95KSwKICAgIHNhZG5lc3M9bWVhbihzYWRuZXNzKSwKICAgIHN1cnByaXNlPW1lYW4oc3VycHJpc2UpLAogICAgdHJ1c3Q9bWVhbih0cnVzdCksCiAgICBuZWdhdGl2ZT1tZWFuKG5lZ2F0aXZlKSwKICAgIHBvc2l0aXZlPW1lYW4ocG9zaXRpdmUpCiAgKQoKcHJlc2lkLnN1bW1hcnk9YXMuZGF0YS5mcmFtZShwcmVzaWQuc3VtbWFyeSkKcm93bmFtZXMocHJlc2lkLnN1bW1hcnkpPXBhc3RlKHRiMSRGaWxlLHRiMSRlZHVsZXZlbCkKa20ucmVzPWttZWFucyhwcmVzaWQuc3VtbWFyeVssLTFdLCAKICAgICAgICAgICAgICBpdGVyLm1heD0zMDAsCiAgICAgICAgICAgICAgNCkKI3BkZigiLi4vb3V0cHV0L3NwZWVjaHRvcGljLnBkZiIsd2lkdGg9OCxoZWlnaHQ9NikKZnZpel9jbHVzdGVyKGttLnJlcywgCiAgICAgICAgICAgICBzdGFuZD1GLCByZXBlbD0gVFJVRSwKICAgICAgICAgICAgIGRhdGEgPSBwcmVzaWQuc3VtbWFyeVssLTFdLCB4bGFiPSIiLCB4YXh0PSJuIiwKICAgICAgICAgICAgIHNob3cuY2x1c3QuY2VudD1GQUxTRSkKI2Rldi5vZmYoKQpgYGAKCiMjIyMgSW50ZXJlc3RpbmcgRmFjdCA1OiBXZSBjYW4gc2VlIHRoYXQgbW9zdCBvZiB0aG9zZSBwcmVzaWRlbnRzIHdpdGggc2ltaWxhciBlZHVjYXRpb24gbGV2ZWwgaGFkIHNpbWlsYXIgdG9waWMgaW4gdGhlaXIgaW5hdWd1cmF0aW9uLgo=